/* NOTICE
 
    Jim - the Java Image Manager, copyright (c) 2005 - 2007 Grant Gardner 
 
    Jim is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Jim is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
    In addition, as a special exception, you are permitted to link this code
    with the 3rd party libraries required to compile this file and to
    distribute a linked combination including them. You must obey the
    GNU General Public License in all respects for all of the code except for
    those 3rd party libraries that are licenced under terms incompatible with the
    GNU General Public License.  
 
 
 NOTICE */

package au.com.lastweekend.jim.io.jpeg;

/**
 * Class representing a JpegSegment structure
 * 
 * @version $Id: JpegSegment.java,v 1.2 2005/06/09 11:15:35 ggardner Exp $
 * @author <a href="mailto:grant@lastweekend.com.au"> <Grant Gardner> </a>
 * @version $Id: JpegSegment.java,v 1.2 2005/06/09 11:15:35 ggardner Exp $
 * @author <a href="mailto:grant@lastweekend.com.au"> <Grant Gardner> </a>
 */
public final class JpegSegment {

    private final byte identifier;
    private final int size;
    private final byte[] data;

    /** Segment boundary marker */
    public static final byte SEGMENT_BOUNDARY = (byte) 0xFF;

    /** APP0 Jpeg segment identifier -- Jfif data. */
    public static final byte SEGMENT_APP0 = (byte) 0xE0;

    /** APP1 Jpeg segment identifier -- where Exif data is kept. */
    public static final byte SEGMENT_APP1 = (byte) 0xE1;

    /** APP2 Jpeg segment identifier. */
    public static final byte SEGMENT_APP2 = (byte) 0xE2;

    /** APP3 Jpeg segment identifier. */
    public static final byte SEGMENT_APP3 = (byte) 0xE3;

    /** APP4 Jpeg segment identifier. */
    public static final byte SEGMENT_APP4 = (byte) 0xE4;

    /** APP5 Jpeg segment identifier. */
    public static final byte SEGMENT_APP5 = (byte) 0xE5;

    /** APP6 Jpeg segment identifier. */
    public static final byte SEGMENT_APP6 = (byte) 0xE6;

    /** APP7 Jpeg segment identifier. */
    public static final byte SEGMENT_APP7 = (byte) 0xE7;

    /** APP8 Jpeg segment identifier. */
    public static final byte SEGMENT_APP8 = (byte) 0xE8;

    /** APP9 Jpeg segment identifier. */
    public static final byte SEGMENT_APP9 = (byte) 0xE9;

    /** APPA Jpeg segment identifier. */
    public static final byte SEGMENT_APPA = (byte) 0xEA;

    /** APPB Jpeg segment identifier. */
    public static final byte SEGMENT_APPB = (byte) 0xEB;

    /** APPC Jpeg segment identifier. */
    public static final byte SEGMENT_APPC = (byte) 0xEC;

    /** APPD Jpeg segment identifier -- IPTC data in here. */
    public static final byte SEGMENT_APPD = (byte) 0xED;

    /** APPE Jpeg segment identifier. */
    public static final byte SEGMENT_APPE = (byte) 0xEE;

    /** APPF Jpeg segment identifier. */
    public static final byte SEGMENT_APPF = (byte) 0xEF;

    /** Start Of Image segment identifier. */
    public static final byte SEGMENT_SOI = (byte) 0xD8;

    /** Define Quantization Table segment identifier. */
    public static final byte SEGMENT_DQT = (byte) 0xDB;

    /** Define Huffman Table segment identifier. */
    public static final byte SEGMENT_DHT = (byte) 0xC4;

    /** Define Restart Interval segment identifier. */
    public static final byte SEGMENT_DRI = (byte) 0xDD;

    /** Start-of-Frame segment identifiers. */
    public static final byte SEGMENT_SOF0 = (byte) 0xC0;
    public static final byte SEGMENT_SOF1 = (byte) 0xC1;

    /** Comment segment identifier */
    public static final byte SEGMENT_COM = (byte) 0xFE;

    /**
     * End of Image
     */
    public static final byte MARKER_EOI = (byte) 0xD9;

    /**
     * Start of Scan (not that length does not include image data)
     */
    public static final byte SEGMENT_SOS = (byte) 0xDA;
    public static final String EXIF_IDENTIFIER = "Exif\0\0";
    public static final byte RESTARTS_END = (byte) 0xD7;
    public static final byte RESTARTS_BEGIN = (byte) 0xD0;

    public JpegSegment(byte identifier, int length, byte[] data) {

        this.identifier = identifier;
        this.size = length;
        this.data = data;
    }

    public byte[] getData() {

        return data;
    }

    public byte getIdentifier() {

        return identifier;
    }

    public int getSize() {

        return size;
    }

    /**
     * 
     * 1 (boundary) + 1 (marker) + 2 (size) + size.
     * 
     * @return number of bytes read to extract this segment.
     * 
     */
    public int getInputStreamLength() {

        return 4 + size;
    }

    public boolean isStartOfScan() {

        return getIdentifier() == SEGMENT_SOS;
    }

    public byte getLow4Bits(int offset) {

        return (byte) (data[offset] & 0x0F);
    }

    public byte getHigh4Bits(int offset) {

        return (byte) ((data[offset] >> 4) & 0x0F);
    }

    public byte get8Bits(int offset) {

        return (byte) (data[offset] & 0xFF);
    }

    public int get16Bits(int offset) {

        return (data[offset] << 8 & 0xFF00) | (data[offset + 1] & 0xFF);
    }
}